import datetime

from django.db import models
from django.db.models import Max

from base.models import CustomSupplier, StoreHouse, Goods
from finance.models import CapitalAccount
from users.models import UserInfo


class SaleOrder(models.Model):
    """销售出库订单"""
    STATUS = (
        (0, '等待付款'),
        (1, '完全付款'),
        (2, '未归还'),
        (3, '已归还'),
    )
    FLAGS = (
        (0, '销售出库'),
        (1, '销售退回'),
        (2, '其他出库'),
        (3, '借出登记'),
    )
    code = models.CharField(verbose_name='出库单编号', max_length=24, blank=True, null=True)
    order_time = models.DateField(verbose_name='出库时间/退回时间', blank=True, null=True)
    customer = models.ForeignKey(to=CustomSupplier, verbose_name='购买客户', blank=True, null=True,
                                 on_delete=models.SET_NULL, db_constraint=False)
    saler = models.ForeignKey(to=UserInfo, verbose_name='销售员', blank=True, null=True,
                              on_delete=models.SET_NULL, db_constraint=False)
    house = models.ForeignKey(to=StoreHouse, verbose_name='销售仓库', blank=True, null=True, on_delete=models.SET_NULL,
                              db_constraint=False)
    total_amount = models.FloatField(verbose_name='总金额', blank=True, null=True)
    amount = models.FloatField(verbose_name='已收款金额', blank=True, null=True)
    status = models.IntegerField(verbose_name='收款状态', blank=True, null=True, choices=STATUS)
    flag = models.IntegerField(verbose_name='销售出库/销售退回', blank=True, null=True, choices=FLAGS)
    imprest = models.BooleanField(verbose_name='直接收款/直接退款标识', blank=True, null=True)
    account = models.ForeignKey(to=CapitalAccount, verbose_name='资金账号', on_delete=models.SET_NULL, blank=True, null=True, db_constraint=False)
    imp_amount = models.FloatField(verbose_name='预付款金额/退回金额', blank=True, null=True)
    address = models.CharField(verbose_name='出货地址', max_length=120, blank=True, null=True)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    oper_user = models.ForeignKey(to=UserInfo, verbose_name='操作员', related_name="sale_users", blank=True, null=True,
                                  on_delete=models.SET_NULL, db_constraint=False)
    order_status = models.IntegerField(verbose_name='付款渠道标识', blank=True, null=True)    # 1为销售出库单，在销售收款单已经生产过收款单
    # balance = models.FloatField(verbose_name='余额', blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.code

    class Meta:
        verbose_name = '销售出库订单'
        verbose_name_plural = verbose_name
        ordering = ["-id"]

    @classmethod
    def get_max_code(cls, flag):
        date = datetime.datetime.now().strftime('%Y%m%d')
        if flag == 0:  # 销售出库
            date = "XSCK{}".format(date)
        elif flag == 1:  # 销售退货
            date = "XSTH{}".format(date)
        elif flag == 2:  # 其他出库
            date = "QTCK{}".format(date)
        elif flag == 3:  # 借出出库
            date = "JCDJ{}".format(date)
        max_code = cls.objects.filter(code__startswith=date).aggregate(max_code=Max("code"))
        max_value = max_code['max_code']
        if max_value is None:
            num = '0001'
            code = '{0}{1}'.format(date, num)
            return code
        else:
            num = str(int(max_value[-4:]) + 1).rjust(4, '0')
            code = '{0}{1}'.format(date, num)
            return code

    def org_instance(self):
        inst = self.__class__.objects.filter(id=self.id).first()
        return inst

    def save(self, *args, **kwargs):
        # 出库单编号
        if self.code == "" or self.code is None:
            self.code = self.__class__.get_max_code(self.flag)
        else:
            if self.id is None:
                exists = self.__class__.objects.filter(code=self.code).exists()
                if exists:
                    self.code = self.__class__.get_max_code(self.flag)

        # 直接付款和实际付款
        if self.id:
            org = self.org_instance()
            org_imprest = org.imprest
            if org_imprest and self.imprest:
                self.amount += (self.imp_amount - org.imp_amount)
            else:
                if self.imprest:
                    self.amount += self.imp_amount
                elif org_imprest:
                    self.amount -= org.imp_amount
        else:
            if self.imprest:  # 直接付款
                self.amount = self.imp_amount

        if self.flag != 3:
            if self.amount and abs(self.total_amount) <= abs(self.amount):
                self.status = 1     # 完全付款
            else:
                self.status = 0

        return super().save(*args, **kwargs)


class SaleOrderDetail(models.Model):
    """销售单明细"""
    sale_order = models.ForeignKey(to=SaleOrder, on_delete=models.CASCADE, related_name="details", blank=True, null=True, db_constraint=False)
    goods = models.ForeignKey(to=Goods, verbose_name='商品名称', blank=True, null=True, on_delete=models.SET_NULL, db_constraint=False)
    batch_num = models.CharField(verbose_name='批号', max_length=16, blank=True, null=True)
    nums = models.FloatField(verbose_name='出库数量', blank=True, null=True)
    price = models.FloatField(verbose_name='单价', blank=True, null=True)
    total_amount = models.FloatField(verbose_name='金额', blank=True, null=True)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    return_nums = models.FloatField(verbose_name='归还数量', blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.sale_order.code

    class Meta:
        verbose_name = '出库单明细'
        verbose_name_plural = verbose_name


class SaleReceipt(models.Model):
    """销售收款单"""
    FLAGS = (
        (0, '销售订单/退货'),
        (1, '销售直接收款'),
        (2, '退货直接付款'),
    )
    code = models.CharField(verbose_name='收款单编号', max_length=24, blank=True, null=True)
    account = models.ForeignKey(to=CapitalAccount, verbose_name='收款账号', on_delete=models.DO_NOTHING, db_constraint=False)
    recv_time = models.DateField(verbose_name='收款时间', blank=True, null=True)
    customer = models.ForeignKey(to=CustomSupplier, verbose_name='付款单位', blank=True, null=True,
                                 on_delete=models.SET_NULL, db_constraint=False)
    user = models.ForeignKey(to=UserInfo, verbose_name='收款人', blank=True, null=True,
                             on_delete=models.SET_NULL, db_constraint=False)
    receivable = models.FloatField(verbose_name='应收款金额', blank=True, null=True)
    amount = models.FloatField(verbose_name='本次收款金额', blank=True, null=True)
    discount_amount = models.FloatField(verbose_name='优惠金额', blank=True, null=True)
    actual_amount = models.FloatField(verbose_name='实际收款', blank=True, null=True)
    oper = models.ForeignKey(to=UserInfo, verbose_name='操作人', related_name="recv_opers", blank=True, null=True,
                             on_delete=models.SET_NULL, db_constraint=False)
    flag = models.IntegerField(verbose_name='销售出库/销售退回', blank=True, null=True, choices=FLAGS)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    sale_order_code = models.CharField(verbose_name='出库单编号', max_length=24, blank=True, null=True)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.code

    class Meta:
        verbose_name = '销售收款单'
        verbose_name_plural = verbose_name
        ordering = ["-id"]

    @classmethod
    def get_max_code(cls):
        date = datetime.datetime.now().strftime('%Y%m%d')
        date = "XSFK{}".format(date)
        max_code = cls.objects.filter(code__startswith=date).aggregate(max_code=Max("code"))
        max_value = max_code['max_code']
        if max_value is None:
            num = '0001'
            code = '{0}{1}'.format(date, num)
            return code
        else:
            num = str(int(max_value[-4:]) + 1).rjust(4, '0')
            code = '{0}{1}'.format(date, num)
            return code

    def save(self, *args, **kwargs):
        """ 收款单编号"""
        if self.code == "" or self.code is None:
            self.code = self.__class__.get_max_code()
        else:
            if self.id is None:
                exists = self.__class__.objects.filter(code=self.code).exists()
                if exists:
                    self.code = self.__class__.get_max_code()

        return super().save(*args, **kwargs)


class SaleReceiptDetail(models.Model):
    """销售收款单明细"""
    CATEGORY = (
        (0, '销售单'),
        (1, '预付款'),
        (2, '会员积分'),
        (3, '活动积分'),
    )

    receipt_order = models.ForeignKey(to=SaleReceipt, verbose_name='收款单编号', related_name="details", on_delete=models.CASCADE, blank=True, null=True, db_constraint=False)
    sale_order = models.ForeignKey(to=SaleOrder, verbose_name='销售出库单', on_delete=models.SET_NULL, blank=True, null=True, db_constraint=False)
    prepay_code = models.CharField(verbose_name='预付款编号', max_length=64, blank=True, null=True)
    amount = models.FloatField(verbose_name='本次收款金额', blank=True, null=True)
    remark = models.CharField(verbose_name='备注', max_length=128, blank=True, null=True)
    category = models.IntegerField(verbose_name='类别', blank=True, null=True, choices=CATEGORY)
    update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    add_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)

    def __str__(self):
        return self.sale_order.code

    class Meta:
        verbose_name = '销售收款单明细'
        verbose_name_plural = verbose_name
